package com.clw.service.impl;

import com.clw.dataobject.Product;
import com.clw.dataobject.PurchaseOrder;
import com.clw.dataobject.PurchaseOrderDetail;
import com.clw.dto.PurchaseOrderDTO;
import com.clw.enums.ResultEnum;
import com.clw.exception.SellException;
import com.clw.repository.ProductRepository;
import com.clw.repository.PurchaseOrderDetailRepository;
import com.clw.repository.PurchaseOrderRepository;
import com.clw.service.PurchaseOrderService;
import com.clw.utils.DateUtils;
import com.clw.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2018-03-01.
 */
@Service
public class PurchaseOrderServiceImpl implements PurchaseOrderService{

    @Autowired
    private PurchaseOrderRepository repository;

    @Autowired
    private PurchaseOrderDetailRepository detailRepository;

    @Autowired
    private ProductRepository productRepository;

    @Override
    public Page<PurchaseOrder> findPage(String purNo, String supplierId, String startTime, String endTime, Pageable pageable) {
        return repository.findAll(getSpecification(purNo,supplierId,startTime,endTime),pageable);
    }

    @Override
    public Long getSize(String purNo, String supplierId, String startTime, String endTime) {
        return repository.count(getSpecification(purNo,supplierId,startTime,endTime));
    }

    @Override
    public List<PurchaseOrderDetail> getDetail(String purNo) {
        return detailRepository.findAllByPurNo(purNo);
    }

    @Override
    public PurchaseOrder findOne(Integer id) {
        return repository.findOne(id);
    }

    @Transactional
    @Override
    public PurchaseOrderDTO add(PurchaseOrderDTO dto) {
        PurchaseOrder purchaseOrder=new PurchaseOrder();
        BeanUtils.copyProperties(dto,purchaseOrder);
        purchaseOrder.setCreateTime(new Date());
        purchaseOrder.setStatus(0);
        PurchaseOrder result=repository.save(purchaseOrder);
        for (PurchaseOrderDetail detail:dto.getDetails()){
            detail.setPurNo(result.getPurNo());
            detailRepository.save(detail);
        }
        return dto;
    }

    @Transactional
    @Override
    public PurchaseOrderDTO update(PurchaseOrderDTO dto) {
        List<PurchaseOrderDetail> oldValueList=detailRepository.findAllByPurNo(dto.getPurNo());
        List<PurchaseOrderDetail> newValueList=dto.getDetails();
        if (newValueList!=null&&newValueList.size()>0){
            for (PurchaseOrderDetail oldValue:oldValueList){
                boolean isUpdate=false;
                for (PurchaseOrderDetail newValue:newValueList){
                    if (oldValue.getId().equals(newValue.getId())){
                        newValue.setPurNo(oldValue.getPurNo());
                        detailRepository.save(newValue);
                        isUpdate=true;
                        break;
                    }
                }
                if (!isUpdate){
                    detailRepository.delete(oldValue);
                }
            }

            for (PurchaseOrderDetail value:newValueList){
                if (StringUtils.isEmpty(value.getId())){
                    value.setPurNo(dto.getPurNo());
                    detailRepository.save(value);
                }
            }

        }
        PurchaseOrder order=repository.findOne(dto.getId());
        BeanUtils.copyProperties(dto,order);
        repository.save(order);
        return dto;
    }

    @Transactional
    @Override
    public PurchaseOrder del(PurchaseOrder purchaseOrder) {
        String purNo=purchaseOrder.getPurNo();
        List<PurchaseOrderDetail> details=detailRepository.findAllByPurNo(purNo);
        repository.delete(purchaseOrder);
        for (PurchaseOrderDetail detail:details){
            detailRepository.delete(detail);
        }
        return purchaseOrder;
    }

    @Override
    public PurchaseOrder save(PurchaseOrder order) {
        return repository.save(order);
    }

    @Transactional
    @Override
    public PurchaseOrder review(PurchaseOrder order) {
        //查询订单明细
        String purNo=order.getPurNo();
        List<PurchaseOrderDetail> detailList=detailRepository.findAllByPurNo(purNo);
        //寻找对应商品
        for (PurchaseOrderDetail detail:detailList){
            Product product=productRepository.findOne(detail.getProductId());
            if (product==null){
                throw new SellException(ResultEnum.PRODUCT_NOT_FOUND);
            }
            Integer count=detail.getCount()+product.getCount();
            product.setCount(count);
        }
        return repository.save(order);

    }

    @Override
    public List<PurchaseOrder> getAllFinishOrder() {
        return repository.findAllByStatus(1);
    }

    private Specification<PurchaseOrder> getSpecification(String purNo, String supplierId, String startTime, String endTime){
        return new Specification<PurchaseOrder>() {
            @Override
            public Predicate toPredicate(Root<PurchaseOrder> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates=new ArrayList<>();
                if (StringUtils.isNotEmpty(purNo)){
                    predicates.add(criteriaBuilder.like(root.get("purNo"),"%"+purNo+"%"));
                }
                if (StringUtils.isNotEmpty(supplierId)){
                    predicates.add(criteriaBuilder.equal(root.get("supplierId"),Integer.parseInt(supplierId)));
                }
                if (StringUtils.isNotEmpty(startTime)){
                    Date start= DateUtils.stringToDate(startTime);
                    predicates.add(criteriaBuilder.greaterThan(root.get("createTime"),start));
                }
                if (StringUtils.isNotEmpty(endTime)){
                    Date end=DateUtils.addDay(endTime,1);
                    predicates.add(criteriaBuilder.lessThan(root.get("createTime"),end));
                }
                return criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
            }
        };
    }
}
